/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_stmt.c                                         */
/*  NOTE      =                                                    */
/*  DATE      = 2014/12/11 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>

#include "frcomm.h"
#include "frstr.h"
#include "frmem.h"
#include "frhash2.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"
#include "frdb_cursor.h"

#include "ora_comm.h"
#include "../ora_core.h"
#include "ora_stmt.h"
#include "../ttc/ora_ttc_proto.h"
#include "ora_util.h"

/*******************************************************************************
*  FUNC     :  释放新建的statement
*  ARGS     :  *p_st_conn                           (ct信息)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_free_req_stmt(Conntrack *p_st_conn)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_req_ora *p_st_req = p_st_session_private->p_st_req;

    if (p_st_req->p_st_stmt != NULL)
        frdb_statement_free(&(p_st_req->p_st_stmt));
}

int ora_create_new_stmt(Conntrack *p_st_conn
                        , Sql_statement **pp_st_stmt)
{
    Sql_statement *p_st_stmt = NULL;
    Sql_resultset *p_st_rs = NULL;
    unsigned long ul_seq = 0L;

    if ((p_st_stmt = frdb_create_statement()) == NULL)
        goto error;

    ul_seq = frct_seq_increase(p_st_conn);

    if ((p_st_rs = frdb_create_resultset(ul_seq)) == NULL)
        goto error;

    if (frdb_add_resultset(p_st_stmt, p_st_rs) != FR_SUCC)
        goto error;

    *pp_st_stmt = p_st_stmt;

    return FR_SUCC;
error:
    frdb_statement_free(&p_st_stmt);
    frdb_resultset_free(&p_st_rs);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  新建一个游标为0的Sql_statement
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  **pp_st_stmt                         (Sql_statement)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_set_new_stmt(Conntrack *p_st_conn
                    , Sql_statement **pp_st_stmt)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_req_ora *p_st_req = p_st_session_private->p_st_req;

    if (ora_create_new_stmt(p_st_conn, pp_st_stmt) != FR_SUCC)
        goto error;

    frdb_statement_free(&(p_st_req->p_st_stmt));
    p_st_req->p_st_stmt = *pp_st_stmt;

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  为ttc7添加一个游标为0的Sql_statement
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  **pp_st_stmt                         (Sql_statement)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_push_ttc7_new_stmt(Conntrack *p_st_conn
                        , Sql_statement **pp_st_stmt)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_req_ora *p_st_req = p_st_session_private->p_st_req;
    Frlist_node *p_st_node = NULL;

    if (ora_create_new_stmt(p_st_conn, pp_st_stmt) != FR_SUCC)
        goto error;

    p_st_node = frlist_node_create(*pp_st_stmt);
    frlist_push(p_st_req->p_st_list_ttc7_stmt, p_st_node);

    return FR_SUCC;
error:
    frdb_statement_free(pp_st_stmt);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  获取一个ttc7的游标为0的Sql_statement
*  ARGS     :  *p_st_conn                           (ct信息)
*  RTN      :  Sql_statement*                       (Sql_statement)
*  NOTE     :
*******************************************************************************/
Sql_statement* ora_pop_ttc7_new_stmt(Conntrack *p_st_conn)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_req_ora *p_st_req = p_st_session_private->p_st_req;
    Frlist_node *p_st_node = NULL;
    Sql_statement *p_st_stmt = NULL;

    if ((p_st_node = frlist_pop(p_st_req->p_st_list_ttc7_stmt)) == NULL)
        return NULL;

    p_st_stmt = (Sql_statement *) FRLIST_GET_NODE_DATA(p_st_node);

    ora_free((void **) &p_st_node);

    return p_st_stmt;
}

/*******************************************************************************
*  FUNC     :  清楚ttc7的新建的Sql_statement
*  ARGS     :  *p_st_conn                           (ct信息)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_clear_ttc7_new_stmt(Conntrack *p_st_conn)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_req_ora *p_st_req = p_st_session_private->p_st_req;

    frlist_remove_all(p_st_req->p_st_list_ttc7_stmt, frdb_statement_node_free);

    return;
}

/*******************************************************************************
*  FUNC     :  根据游标查找statement
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  l_cursor_id                          (游标ID)
*  RTN      :  Sql_statement*                       (Sql_statement*)
*  NOTE     :
*******************************************************************************/
Sql_statement* ora_get_stmt(Conntrack *p_st_conn
                            , long l_cursor_id)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    Sql_statement *p_st_stmt = NULL;

    p_st_stmt = frdb_get_statement(p_st_session_private->p_hash_stmt, l_cursor_id);
    if (p_st_stmt == NULL &&
            p_st_session_private->p_st_req != NULL &&
            p_st_session_private->p_st_req->p_st_stmt != NULL &&
            p_st_session_private->p_st_req->p_st_stmt->l_cursor_id == l_cursor_id)
    {
        ORA_PRINT_DBG("get stmt of cursor:[%ld] from req\n", l_cursor_id);
        return p_st_session_private->p_st_req->p_st_stmt;
    }

    if (p_st_stmt == NULL)
        ORA_PRINT_WARN("can not find cursor:[%ld]\n", l_cursor_id);
    else
        ORA_PRINT_DBG("get stmt of cursor:[%ld] from hash\n", l_cursor_id);

    return p_st_stmt;
}

/*******************************************************************************
*  FUNC     :  获取新建的statement
*  ARGS     :  *p_st_conn                           (ct信息)
*  RTN      :  Sql_statement*                       (Sql_statement*)
*  NOTE     :
*******************************************************************************/
Sql_statement* ora_get_new_stmt(Conntrack *p_st_conn)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);

    if (p_st_session_private->p_st_req != NULL &&
            p_st_session_private->p_st_req->p_st_stmt != NULL)
    {
        ORA_PRINT_DBG("get new stmt of cursor:[0]\n");
        return p_st_session_private->p_st_req->p_st_stmt;
    }

    return NULL;
}

/*******************************************************************************
*  FUNC     :  根据当前所记的游标查找statement
*  ARGS     :  *p_st_conn                           (ct信息)
*  RTN      :  Sql_statement*                       (Sql_statement*)
*  NOTE     :
*******************************************************************************/
Sql_statement* ora_get_current_stmt(Conntrack *p_st_conn)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_ora_curr_session *p_st_curr_sess = p_st_session_private->p_st_curr_sess;

    return ora_get_stmt(p_st_conn, p_st_curr_sess->ul_cursor);
}

/*******************************************************************************
*  FUNC     :  释放statement的哈希桶
*  ARGS     :  *p_st_session_private                (Oracle私有信息)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_free_private_stmt(L7session_ora_private *p_st_session_private)
{
    if (p_st_session_private == NULL || p_st_session_private->p_hash_stmt == NULL)
        return;

    frhash2_free(p_st_session_private->p_hash_stmt, frdb_statement_node_free);

    ora_free((void **) &p_st_session_private->p_hash_stmt);
    return;
}

/*******************************************************************************
*  FUNC     :  添加define的meta信息
*  ARGS     :  *p_st_stmt                           (Sql_statement)
*           :  i_oacdty                             (oacdty)
*           :  i_oacmxl                             (oacmxl)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_stmt_add_define_metadata(Sql_statement *p_st_stmt
                                , Ora_metadata st_ora_metadata)
{
//    ORA_PRINT_INFO("add define metadata i_oacdty:[%d] i_oacflag:[%d] i_oacmxl:[%d]\n", i_oacdty, i_oacflag, i_oacmxl);
    ORA_PRINT_INFO("add define metadata\n");
    Sql_metadata_info *p_st_metadata = NULL;

    if ((p_st_metadata = (Sql_metadata_info *) frmalloc(sizeof(Sql_metadata_info))) == NULL)
    {
        ORA_MALLOCK_ERR;
        goto error;
    }
    memset(p_st_metadata, 0x00, sizeof(Sql_metadata_info));
    p_st_metadata->i_ora_dml_returned_param = FR_NO;
    p_st_metadata->i_data_type = st_ora_metadata.s_oacdty;
    p_st_metadata->s_ora_oacdty = st_ora_metadata.s_oacdty;
    p_st_metadata->s_ora_oacflg = st_ora_metadata.s_oacflg;
    p_st_metadata->s_ora_oacpre = st_ora_metadata.s_oacpre;
    p_st_metadata->s_ora_oacscl = st_ora_metadata.s_oacscl;
    p_st_metadata->i_ora_oacmxl = st_ora_metadata.i_oacmxl;
    p_st_metadata->i_ora_oacmal = st_ora_metadata.i_oacmal;
    p_st_metadata->i_ora_oacfl2 = st_ora_metadata.i_oacfl2;
    p_st_metadata->i_ora_oacvsn = st_ora_metadata.i_oacvsn;
    p_st_metadata->i_ora_oaccsi = st_ora_metadata.i_oaccsi;
    p_st_metadata->s_ora_oaccsfrm = st_ora_metadata.s_oaccsfrm;
    p_st_metadata->i_ora_oacmxlc = st_ora_metadata.i_oacmxlc;
    p_st_metadata->i_isnullbydescribe = st_ora_metadata.i_oacmxl == 0 ? FR_YES : FR_NO;
//    ORA_PRINT_DBG("st_metadata_info i_data_type:[%d] oacflag:[%d]\n", p_st_metadata->i_data_type, p_st_metadata->s_ora_oacflg);
    if (frdb_add_metadata_info(p_st_stmt, FRDB_DEFINE, p_st_metadata) != FR_SUCC)
        goto error;

    return FR_SUCC;
error:
    ora_free((void **) &p_st_metadata);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  添加bind的meta信息
*  ARGS     :  *p_st_stmt                           (Sql_statement)
*           :  i_oacdty                             (oacdty)
*           :  i_oacmxl                             (oacmxl)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_stmt_add_bind_metadata(Sql_statement *p_st_stmt
                            , Ora_metadata st_ora_metadata)
{
//    ORA_PRINT_INFO("add bind metadata i_oacdty:[%d] i_oacflag:[%d] i_oacmxl:[%d]\n", i_oacdty, i_oacflag, i_oacmxl);
    ORA_PRINT_INFO("add bind metadata\n");
    Sql_metadata_info *p_st_metadata = NULL;

    if ((p_st_metadata = (Sql_metadata_info *) frmalloc(sizeof(Sql_metadata_info))) == NULL)
    {
        ORA_MALLOCK_ERR;
        goto error;
    }
    memset(p_st_metadata, 0x00, sizeof(Sql_metadata_info));
    p_st_metadata->i_ora_dml_returned_param = FR_NO;
    p_st_metadata->i_data_type = st_ora_metadata.s_oacdty;
    p_st_metadata->s_ora_oacdty = st_ora_metadata.s_oacdty;
    p_st_metadata->s_ora_oacflg = st_ora_metadata.s_oacflg;
    p_st_metadata->s_ora_oacpre = st_ora_metadata.s_oacpre;
    p_st_metadata->s_ora_oacscl = st_ora_metadata.s_oacscl;
    p_st_metadata->i_ora_oacmxl = st_ora_metadata.i_oacmxl;
    p_st_metadata->i_ora_oacmal = st_ora_metadata.i_oacmal;
    p_st_metadata->i_ora_oacfl2 = st_ora_metadata.i_oacfl2;
    p_st_metadata->i_ora_oacvsn = st_ora_metadata.i_oacvsn;
    p_st_metadata->i_ora_oaccsi = st_ora_metadata.i_oaccsi;
    p_st_metadata->s_ora_oaccsfrm = st_ora_metadata.s_oaccsfrm;
    p_st_metadata->i_ora_oacmxlc = st_ora_metadata.i_oacmxlc;
    p_st_metadata->i_isnullbydescribe = st_ora_metadata.i_oacmxl == 0 ? FR_YES : FR_NO;
    ORA_PRINT_DBG("st_metadata_info "
                  "i_data_type:[0x%02x] "
                  "oacflag:[0x%02x] "
                  "oacpre:[0x%02x] "
                  "oacscl:[0x%02x] "
                  "oacmxl:[0x%04x] "
                  "oacmal:[0x%02x] "
                  "oacfl2:[0x%02x] "
                  "oacvsn:[0x%02x] "
                  "oaccsi:[0x%04x] "
                  "oaccsfrm:[0x%02x] "
                  "oacmxlc:[0x%02x]\n",
                  p_st_metadata->i_data_type,
                  p_st_metadata->s_ora_oacflg,
                  p_st_metadata->s_ora_oacpre,
                  p_st_metadata->s_ora_oacscl,
                  p_st_metadata->i_ora_oacmxl,
                  p_st_metadata->i_ora_oacmal,
                  p_st_metadata->i_ora_oacfl2,
                  p_st_metadata->i_ora_oacvsn,
                  p_st_metadata->i_ora_oaccsi,
                  p_st_metadata->s_ora_oaccsfrm,
                  p_st_metadata->i_ora_oacmxlc
    );
    if (frdb_add_metadata_info(p_st_stmt, FRDB_BIND, p_st_metadata) != FR_SUCC)
        goto error;

    return FR_SUCC;
error:
    ora_free((void **) &p_st_metadata);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  添加select字段的meta信息
*  ARGS     :  *p_st_stmt                           (Sql_statement)
*           :  i_oacdty                             (oacdty)
*           :  i_oacmxl                             (oacmxl)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_stmt_add_column_metadata(Sql_statement *p_st_stmt
                                , Ora_metadata st_ora_metadata)
{
//    ORA_PRINT_INFO("add column metadata i_oacdty:[%d] i_oacflag:[%d] i_oacmxl:[%d]\n", i_oacdty, i_oacflag, i_oacmxl);
    ORA_PRINT_INFO("add column metadata\n");
    Sql_metadata_info *p_st_metadata = NULL;

    if ((p_st_metadata = (Sql_metadata_info *) frmalloc(sizeof(Sql_metadata_info))) == NULL)
    {
        ORA_MALLOCK_ERR;
        goto error;
    }
    memset(p_st_metadata, 0x00, sizeof(Sql_metadata_info));
    p_st_metadata->i_ora_dml_returned_param = FR_YES;
    p_st_metadata->i_data_type = st_ora_metadata.s_oacdty;
    p_st_metadata->s_ora_oacdty = st_ora_metadata.s_oacdty;
    p_st_metadata->s_ora_oacflg = st_ora_metadata.s_oacflg;
    p_st_metadata->s_ora_oacpre = st_ora_metadata.s_oacpre;
    p_st_metadata->s_ora_oacscl = st_ora_metadata.s_oacscl;
    p_st_metadata->i_ora_oacmxl = st_ora_metadata.i_oacmxl;
    p_st_metadata->i_ora_oacmal = st_ora_metadata.i_oacmal;
    p_st_metadata->i_ora_oacfl2 = st_ora_metadata.i_oacfl2;
    p_st_metadata->i_ora_oacvsn = st_ora_metadata.i_oacvsn;
    p_st_metadata->i_ora_oaccsi = st_ora_metadata.i_oaccsi;
    p_st_metadata->s_ora_oaccsfrm = st_ora_metadata.s_oaccsfrm;
    p_st_metadata->i_ora_oacmxlc = st_ora_metadata.i_oacmxlc;
    p_st_metadata->i_isnullbydescribe = st_ora_metadata.i_oacmxl == 0 ? FR_YES : FR_NO;
//    ORA_PRINT_DBG("st_metadata_info i_data_type:[%d] oacflag:[%d]\n", p_st_metadata->i_data_type, p_st_metadata->s_ora_oacflg);
    if (frdb_add_metadata_info(p_st_stmt, FRDB_COLUMN, p_st_metadata) != FR_SUCC)
        goto error;

//    p_st_stmt->i_is_dml_returning = FR_YES;

    return FR_SUCC;
error:
    ora_free((void **) &p_st_metadata);
    return FR_FAIL;
}

Frlist_node *ora_create_closed_cursor_node(unsigned long ul_cursor)
{
    Ora_cursor *p_st_ora_cursor = NULL;
    Frlist_node *p_st_node_cursor = NULL;

    if ((p_st_ora_cursor = (Ora_cursor *) frmalloc(sizeof(Ora_cursor))) == NULL)
    {
        ORA_MALLOCK_ERR;
        return NULL;
    }
    memset(p_st_ora_cursor, 0x00, sizeof(Ora_cursor));
    p_st_ora_cursor->ul_cursor = ul_cursor;

    if ((p_st_node_cursor = frlist_node_create(p_st_ora_cursor)) == NULL)
    {
        ora_free((void **) &p_st_ora_cursor);
        return NULL;
    }

    return p_st_node_cursor;
}

/*******************************************************************************
*  FUNC     :  添加需要关闭的游标
*  ARGS     :  *p_st_sess                           (Oracle私有的session)
*           :  ul_cursor                            (游标ID)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_add_closed_cursor(L7session_ora *p_st_sess
                        , unsigned long ul_cursor)
{
    Ora_cursor *ora_cursor = NULL;
    Frlist_node *p_st_node_cursor = NULL;

    if ((ora_cursor = (Ora_cursor *) frmalloc(sizeof(Ora_cursor))) == NULL)
    {
        ORA_MALLOCK_ERR;
        goto error;
    }
    memset(ora_cursor, 0x00, sizeof(Ora_cursor));
    ora_cursor->ul_cursor = ul_cursor;
    ORA_PRINT_DBG("add cursor:[%lu] to closed cursor list\n", ora_cursor->ul_cursor);

    p_st_node_cursor = frlist_node_create(ora_cursor);
    frlist_push(p_st_sess->p_list_closed_cursors, p_st_node_cursor);

    return FR_SUCC;
error:
    ora_free((void **) &ora_cursor);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  更新指定statement的所有resultset的包长和时间信息
*  ARGS     :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_stmt                           (Sql_statement)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_set_resultset_resp(L7_ora_packet *p_st_ora_packet
                        , Sql_statement *p_st_stmt)
{
    Frlist_node *p_st_node_rs = NULL;
    Sql_resultset *p_st_rs = NULL;

    // 循环取出所有的resultset设置包长和时间
    p_st_node_rs = FRLIST_FIRST_NODE(&(p_st_stmt->st_resultset_list));
    while (p_st_node_rs)
    {
        p_st_rs = (Sql_resultset *) FRLIST_GET_NODE_DATA(p_st_node_rs);

        ORA_PRINT_TIMEVAL("set resp time st_timestamp_first", p_st_ora_packet->st_timestamp_first);
        ORA_PRINT_TIMEVAL("set resp time st_timestamp_last", p_st_ora_packet->st_timestamp_last);
        // 设置l4层信息
        if (frdb_set_resultset_resp(p_st_stmt, FRDB_SPECIFIED, p_st_rs->l_id,
                                    bytebuff_length(p_st_ora_packet->p_st_packet), 0, NULL,
                                    &(p_st_ora_packet->st_timestamp_first), &(p_st_ora_packet->st_timestamp_last)) != FR_SUCC)
            goto error;

        p_st_node_rs = FRLIST_NEXT_NODE(p_st_node_rs);
    }

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  上报已被关闭的statement
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_hash_report                    (数据上报)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_report_closed_stmt(Conntrack *p_st_conn
                            , L7session_ora *p_st_sess
                            , L7_ora_packet *p_st_ora_packet
                            , Frhash_header *p_st_hash_report)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    Frlist_header *p_list_closed_cursors = p_st_sess->p_list_closed_cursors;
    Sql_statement *p_st_stmt = NULL;
    Frlist_node *p_st_node_cursor = NULL;
    Ora_cursor *p_st_ora_cursor = NULL;
    unsigned long ul_cursor = 0L;

    int i_closed_count = 0;

    // 取出需要关闭的游标
    p_st_node_cursor = frlist_remove_head(p_list_closed_cursors);
    while (p_st_node_cursor)
    {
        p_st_ora_cursor = (Ora_cursor *) FRLIST_GET_NODE_DATA(p_st_node_cursor);

        ul_cursor = p_st_ora_cursor->ul_cursor;

        // 从关闭游标的列表中先清除该节点
        frlist_node_free(p_list_closed_cursors, p_st_node_cursor, 0, frlist_node_data_free);

        if ((p_st_stmt = ora_get_stmt(p_st_conn, ul_cursor)) != NULL)
        {
            ORA_PRINT_DBG("get closed cursor:[%lu]\n", ul_cursor);

            ora_report_stmt_resp(p_st_conn, p_st_sess, p_st_stmt, p_st_hash_report, FR_NO);
            i_closed_count++;

            frhash2_delLong(p_st_session_private->p_hash_stmt, p_st_stmt->l_cursor_id, frdb_statement_node_free);
        }
        else
            ORA_PRINT_EMERG("can not find current cursor:[%lu]\n", ul_cursor);

        p_st_node_cursor = frlist_remove_head(p_list_closed_cursors);
    }
    if (i_closed_count > 1)
    {
        ORA_PRINT_ALERT("closed multiple stmt %d\n", i_closed_count);
        if (i_closed_count > p_st_sess->i_closed_count)
            p_st_sess->i_closed_count = i_closed_count;
    }

    return;
}

/*******************************************************************************
*  FUNC     :  上报所有的statement
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_hash_report                    (数据上报)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_report_all_stmt(Conntrack *p_st_conn
                        , L7session_ora *p_st_sess
                        , Frhash_header *p_st_hash_report)
{
    ORA_PRINT_INFO("report all stmt\n");
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    unsigned int ui_loop = 0;
    unsigned long long ull_loop = 0LL;
    Frlist_header *p_st_lst_hdr = NULL;
    Frlist_node *p_st_node = NULL;
    Sql_statement *p_st_stmt = NULL;

    FRHASH_LOOP(ui_loop, p_st_session_private->p_hash_stmt, p_st_lst_hdr)
    {
        p_st_node = FRLIST_FIRST_NODE(p_st_lst_hdr);
        while (p_st_node)
        {
            p_st_stmt = (Sql_statement *) FRLIST_GET_NODE_DATA(p_st_node);
            if (p_st_stmt)
                ora_report_stmt_resp(p_st_conn, p_st_sess, p_st_stmt, p_st_hash_report, FR_NO);

            p_st_node = FRLIST_NEXT_NODE(p_st_node);
            ull_loop++;
        }
    }
    if (ull_loop > 0LL)
        ORA_PRINT_WARN("reported %llu stmt\n", ull_loop);
    return;
}
